package vectors;

public class Direction implements Location{
	
	private final int dof;
	
	private double[] phis;
	private double theta;

	public Direction(double theta){
		this(new double[0], theta);
	}
	
	// Each phi range is 0..PI, and theta is 0..2PI
	public Direction(double[] phis, double theta){
		this.phis = phis;
		this.theta = theta;
		this.dof = phis.length+1;
	}
	
	// This assumes that when each phi is 0, it points at an axis, as long as the ones before it were not 0.
	// theta=0 points at X, theta = pi/2 points at Y, again, as long as no phis before it were 0
	public Vector generateUnitVector(){
		double[] vals = new double[dof+1];
		double curSineTotal = 1;
		for(int i=0;i<phis.length;i++){
			vals[i] = curSineTotal*Math.cos(phis[i]);
			curSineTotal*=Math.sin(phis[i]);
		}
		vals[phis.length] = curSineTotal*Math.cos(theta);
		vals[phis.length+1] = curSineTotal*Math.sin(theta);
		return new Vector(vals);
	}
	
	public double acos(Direction dir) {
		return Math.acos(this.generateUnitVector().dot(dir.generateUnitVector()));
	}
	
	public int getDOF(){
		return dof;
	}
	
	public void setTheta(double theta){
		this.theta = theta;
	}
	
	public double getPhi(int index){
		return phis[index];
	}
	
	public void setPhi(int index, double value){
		phis[index] = value;
	}

	public double getTheta() {
		return theta;
	}
	
	/**
	 * A string representation of this direction
	 * 
	 * @return  the direction as: [phi1][phi2]...[phin],[theta]
	 */
	public String toString(){
		StringBuffer str = new StringBuffer();
		for(int i=0;i<phis.length;i++){
			str.append("[").append(phis[i]).append("]");
		}
		str.append(",[").append(theta).append("]");
		return str.toString();
	}

	public static Direction random(int dof) {
		// TODO probably can speed this up and make more evenly distrubted
		return Vector.random(dof+1).times(2).plus(-1).generateDirection();
	}
}
